#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AI智能分支剧情童话书
基于ERNIE-4.5-0.3B-Paddle和智源知识库的交互式童话应用

核心功能：
1. 多模态感知（文字、图像、语音）
2. 智源知识库增强
3. 个性化剧情生成
4. 教育价值融合
"""

import os
import json
import random
import asyncio
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
from datetime import datetime
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@dataclass
class Character:
    """角色类"""
    name: str
    personality: str
    skills: List[str]
    age_group: str  # "3-6", "7-10", "11-14"
    avatar_path: Optional[str] = None

@dataclass
class StoryNode:
    """故事节点类"""
    id: str
    title: str
    content: str
    choices: List[Dict[str, str]]  # [{"text": "选择文本", "next_id": "下一节点ID", "knowledge": "知识点"}]
    knowledge_points: List[str]
    difficulty_level: int  # 1-5
    educational_value: str
    image_prompt: Optional[str] = None
    audio_prompt: Optional[str] = None

@dataclass
class UserProfile:
    """用户画像类"""
    name: str
    age: int
    interests: List[str]
    learning_goals: List[str]
    completed_stories: List[str]
    knowledge_level: Dict[str, int]  # {"science": 3, "history": 2, ...}

class ZhiyuanKnowledgeBase:
    """智源知识库接口"""
    
    def __init__(self):
        self.knowledge_domains = {
            "science": "科学知识",
            "history": "历史文化", 
            "literature": "文学艺术",
            "mathematics": "数学逻辑",
            "nature": "自然环境",
            "social": "社会生活"
        }
    
    async def get_knowledge_by_domain(self, domain: str, age_group: str) -> Dict:
        """根据领域和年龄组获取知识点"""
        # 这里模拟调用智源知识库API
        knowledge_data = {
            "science": {
                "3-6": ["动物的家在哪里", "植物需要什么才能长大", "天空为什么是蓝色的"],
                "7-10": ["地球为什么会转动", "恐龙为什么消失了", "彩虹是怎么形成的"],
                "11-14": ["DNA的秘密", "黑洞的奥秘", "量子物理入门"]
            },
            "history": {
                "3-6": ["古代的房子是什么样的", "古人怎么生活", "传统节日的故事"],
                "7-10": ["丝绸之路的故事", "古代四大发明", "历史上的英雄人物"],
                "11-14": ["文明的起源", "科技革命", "世界历史大事件"]
            }
        }
        
        return {
            "domain": domain,
            "age_group": age_group,
            "knowledge_points": knowledge_data.get(domain, {}).get(age_group, []),
            "difficulty": self._get_difficulty_by_age(age_group)
        }
    
    def _get_difficulty_by_age(self, age_group: str) -> int:
        """根据年龄组确定难度等级"""
        difficulty_map = {"3-6": 1, "7-10": 3, "11-14": 5}
        return difficulty_map.get(age_group, 3)

class ERNIEModelInterface:
    """文心大模型接口"""
    
    def __init__(self, model_path: str):
        self.model_path = model_path
        self.model = None
        logger.info(f"初始化ERNIE模型: {model_path}")
    
    async def load_model(self):
        """加载模型"""
        try:
            # 这里应该加载实际的ERNIE-4.5-0.3B-Paddle模型
            logger.info("正在加载ERNIE-4.5-0.3B-Paddle模型...")
            # 模拟加载过程
            await asyncio.sleep(2)
            self.model = "ERNIE-4.5-0.3B-Paddle-Loaded"
            logger.info("模型加载完成")
        except Exception as e:
            logger.error(f"模型加载失败: {e}")
            raise
    
    async def generate_story_content(self, prompt: str, knowledge_context: str, user_profile: UserProfile) -> str:
        """生成故事内容"""
        if not self.model:
            await self.load_model()
        
        # 构建提示词
        full_prompt = f"""
        基于以下信息生成适合的童话故事内容：
        
        用户信息：
        - 姓名：{user_profile.name}
        - 年龄：{user_profile.age}岁
        - 兴趣：{', '.join(user_profile.interests)}
        - 学习目标：{', '.join(user_profile.learning_goals)}
        
        知识背景：{knowledge_context}
        
        故事提示：{prompt}
        
        请生成一段富有想象力、教育意义且适合该年龄段的童话故事内容。
        """
        
        # 这里应该调用实际的ERNIE模型
        # 现在使用模拟生成
        story_templates = [
            f"在一个神奇的森林里，住着一只聪明的小{random.choice(['狐狸', '兔子', '松鼠'])}...",
            f"很久很久以前，有一个美丽的王国，那里的人们都很善良...",
            f"在遥远的星球上，住着一群可爱的外星朋友..."
        ]
        
        return random.choice(story_templates) + f"（融入知识点：{knowledge_context}）"
    
    async def generate_image_description(self, story_content: str) -> str:
        """生成图像描述"""
        # 基于故事内容生成图像描述
        return f"一幅温馨的童话插画，描绘了：{story_content[:50]}..."
    
    async def analyze_user_choice(self, choice_text: str, user_profile: UserProfile) -> Dict:
        """分析用户选择，提供个性化反馈"""
        return {
            "choice_analysis": f"很好的选择！这体现了{user_profile.name}的{random.choice(['勇敢', '智慧', '善良'])}品质。",
            "learning_insight": "通过这个选择，我们学到了...",
            "next_suggestion": "接下来可以探索..."
        }

class StoryGenerator:
    """故事生成器"""
    
    def __init__(self, ernie_model: ERNIEModelInterface, knowledge_base: ZhiyuanKnowledgeBase):
        self.ernie_model = ernie_model
        self.knowledge_base = knowledge_base
        self.story_templates = self._load_story_templates()
    
    def _load_story_templates(self) -> Dict:
        """加载故事模板"""
        return {
            "adventure": {
                "title": "神奇冒险之旅",
                "themes": ["勇气", "友谊", "探索"],
                "settings": ["森林", "城堡", "海洋", "太空"]
            },
            "learning": {
                "title": "知识探索之旅", 
                "themes": ["学习", "发现", "思考"],
                "settings": ["图书馆", "实验室", "博物馆", "学校"]
            },
            "friendship": {
                "title": "友谊的力量",
                "themes": ["友谊", "合作", "分享"],
                "settings": ["村庄", "公园", "家庭", "学校"]
            }
        }
    
    async def create_personalized_story(self, user_profile: UserProfile, story_type: str = "adventure") -> List[StoryNode]:
        """创建个性化故事"""
        # 根据用户兴趣选择知识领域
        primary_domain = self._select_knowledge_domain(user_profile.interests)
        age_group = self._get_age_group(user_profile.age)
        
        # 获取相关知识点
        knowledge_data = await self.knowledge_base.get_knowledge_by_domain(primary_domain, age_group)
        
        # 生成故事节点
        story_nodes = []
        
        # 开始节点
        start_content = await self.ernie_model.generate_story_content(
            f"开始一个关于{story_type}的故事",
            f"知识领域：{primary_domain}，知识点：{knowledge_data['knowledge_points'][0] if knowledge_data['knowledge_points'] else '基础知识'}",
            user_profile
        )
        
        start_node = StoryNode(
            id="start",
            title="故事开始",
            content=start_content,
            choices=[
                {"text": "勇敢地向前走", "next_id": "choice1_brave", "knowledge": "勇气的重要性"},
                {"text": "仔细观察周围", "next_id": "choice1_observe", "knowledge": "观察力的培养"},
                {"text": "寻找朋友帮助", "next_id": "choice1_help", "knowledge": "合作的价值"}
            ],
            knowledge_points=knowledge_data['knowledge_points'][:1],
            difficulty_level=knowledge_data['difficulty'],
            educational_value=f"培养{primary_domain}领域的基础认知"
        )
        
        story_nodes.append(start_node)
        
        # 生成后续节点（简化版本）
        for i, choice in enumerate(start_node.choices):
            node_content = await self.ernie_model.generate_story_content(
                f"基于选择'{choice['text']}'继续故事",
                choice['knowledge'],
                user_profile
            )
            
            node = StoryNode(
                id=choice['next_id'],
                title=f"第{i+1}章",
                content=node_content,
                choices=[
                    {"text": "继续探索", "next_id": "end", "knowledge": "探索精神"},
                    {"text": "回到起点", "next_id": "start", "knowledge": "反思能力"}
                ],
                knowledge_points=[choice['knowledge']],
                difficulty_level=knowledge_data['difficulty'],
                educational_value=f"深化理解{choice['knowledge']}"
            )
            story_nodes.append(node)
        
        return story_nodes
    
    def _select_knowledge_domain(self, interests: List[str]) -> str:
        """根据兴趣选择知识领域"""
        domain_mapping = {
            "动物": "science",
            "植物": "science", 
            "历史": "history",
            "故事": "literature",
            "数学": "mathematics",
            "自然": "nature"
        }
        
        for interest in interests:
            if interest in domain_mapping:
                return domain_mapping[interest]
        
        return "science"  # 默认科学领域
    
    def _get_age_group(self, age: int) -> str:
        """根据年龄确定年龄组"""
        if age <= 6:
            return "3-6"
        elif age <= 10:
            return "7-10"
        else:
            return "11-14"

class FairyTaleBookApp:
    """童话书主应用"""
    
    def __init__(self, model_path: str = "./ERNIE-4.5-0.3B-Paddle"):
        self.ernie_model = ERNIEModelInterface(model_path)
        self.knowledge_base = ZhiyuanKnowledgeBase()
        self.story_generator = StoryGenerator(self.ernie_model, self.knowledge_base)
        self.current_user: Optional[UserProfile] = None
        self.current_story: List[StoryNode] = []
        self.current_node_id: str = "start"
        self.user_progress: Dict = {}
    
    async def initialize(self):
        """初始化应用"""
        logger.info("正在初始化AI童话书应用...")
        await self.ernie_model.load_model()
        logger.info("应用初始化完成")
    
    def create_user_profile(self, name: str, age: int, interests: List[str], learning_goals: List[str]) -> UserProfile:
        """创建用户画像"""
        user_profile = UserProfile(
            name=name,
            age=age,
            interests=interests,
            learning_goals=learning_goals,
            completed_stories=[],
            knowledge_level={"science": 1, "history": 1, "literature": 1, "mathematics": 1}
        )
        self.current_user = user_profile
        logger.info(f"创建用户画像：{name}, {age}岁")
        return user_profile
    
    async def start_new_story(self, story_type: str = "adventure") -> StoryNode:
        """开始新故事"""
        if not self.current_user:
            raise ValueError("请先创建用户画像")
        
        logger.info(f"为用户 {self.current_user.name} 生成新故事：{story_type}")
        self.current_story = await self.story_generator.create_personalized_story(
            self.current_user, story_type
        )
        self.current_node_id = "start"
        
        return self.get_current_node()
    
    def get_current_node(self) -> StoryNode:
        """获取当前故事节点"""
        for node in self.current_story:
            if node.id == self.current_node_id:
                return node
        raise ValueError(f"未找到节点ID: {self.current_node_id}")
    
    async def make_choice(self, choice_index: int) -> Tuple[StoryNode, Dict]:
        """做出选择并获取反馈"""
        current_node = self.get_current_node()
        
        if choice_index >= len(current_node.choices):
            raise ValueError("无效的选择索引")
        
        choice = current_node.choices[choice_index]
        
        # 分析用户选择
        choice_analysis = await self.ernie_model.analyze_user_choice(
            choice['text'], self.current_user
        )
        
        # 更新当前节点
        self.current_node_id = choice['next_id']
        
        # 更新用户进度
        self._update_user_progress(choice['knowledge'])
        
        try:
            next_node = self.get_current_node()
            return next_node, choice_analysis
        except ValueError:
            # 如果到达故事结尾
            return self._create_ending_node(), choice_analysis
    
    def _update_user_progress(self, knowledge_point: str):
        """更新用户学习进度"""
        if self.current_user.name not in self.user_progress:
            self.user_progress[self.current_user.name] = {
                "learned_concepts": [],
                "story_count": 0,
                "last_activity": datetime.now().isoformat()
            }
        
        progress = self.user_progress[self.current_user.name]
        if knowledge_point not in progress["learned_concepts"]:
            progress["learned_concepts"].append(knowledge_point)
        progress["last_activity"] = datetime.now().isoformat()
    
    def _create_ending_node(self) -> StoryNode:
        """创建结尾节点"""
        return StoryNode(
            id="end",
            title="故事结束",
            content=f"恭喜{self.current_user.name}！你完成了这个精彩的故事。通过这次冒险，你学到了很多新知识！",
            choices=[
                {"text": "开始新故事", "next_id": "new_story", "knowledge": "持续学习"},
                {"text": "查看学习报告", "next_id": "report", "knowledge": "自我反思"}
            ],
            knowledge_points=["故事完成", "学习总结"],
            difficulty_level=1,
            educational_value="培养完成任务的成就感和持续学习的动力"
        )
    
    def get_learning_report(self) -> Dict:
        """获取学习报告"""
        if not self.current_user or self.current_user.name not in self.user_progress:
            return {"message": "暂无学习记录"}
        
        progress = self.user_progress[self.current_user.name]
        return {
            "user_name": self.current_user.name,
            "learned_concepts": progress["learned_concepts"],
            "concept_count": len(progress["learned_concepts"]),
            "story_count": progress["story_count"],
            "last_activity": progress["last_activity"],
            "recommendations": self._generate_recommendations()
        }
    
    def _generate_recommendations(self) -> List[str]:
        """生成学习建议"""
        recommendations = [
            "继续探索科学知识的奥秘",
            "尝试历史主题的故事",
            "挑战更高难度的故事内容",
            "邀请朋友一起阅读故事"
        ]
        return random.sample(recommendations, 2)

# 示例使用
async def main():
    """主函数示例"""
    # 创建应用实例
    app = FairyTaleBookApp()
    
    # 初始化
    await app.initialize()
    
    # 创建用户画像
    user = app.create_user_profile(
        name="小明",
        age=8,
        interests=["动物", "冒险", "科学"],
        learning_goals=["了解动物习性", "培养勇气", "学习科学知识"]
    )
    
    print(f"欢迎 {user.name}！让我们开始一个神奇的故事之旅吧！")
    
    # 开始新故事
    current_node = await app.start_new_story("adventure")
    
    print(f"\n=== {current_node.title} ===")
    print(current_node.content)
    print(f"\n知识点：{', '.join(current_node.knowledge_points)}")
    print(f"教育价值：{current_node.educational_value}")
    
    print("\n请选择：")
    for i, choice in enumerate(current_node.choices):
        print(f"{i+1}. {choice['text']}")
    
    # 模拟用户选择
    choice_index = 0  # 选择第一个选项
    next_node, analysis = await app.make_choice(choice_index)
    
    print(f"\n=== 选择分析 ===")
    print(analysis['choice_analysis'])
    print(analysis['learning_insight'])
    
    print(f"\n=== {next_node.title} ===")
    print(next_node.content)
    
    # 获取学习报告
    report = app.get_learning_report()
    print(f"\n=== 学习报告 ===")
    print(f"已学习概念：{report['learned_concepts']}")
    print(f"学习建议：{report['recommendations']}")

if __name__ == "__main__":
    asyncio.run(main())